package datapack

import (
	"broker/interface/imodel"
	"broker/interface/iserver"
	"bytes"
	"encoding/binary"
	"io"
)

// BaseDataPack  封包拆包具体模块
type BaseDataPack struct {
}

// GetMessageHeader 获取包头方法
func (dp *BaseDataPack) GetMessageHeader(connection iserver.IConnection) (byte, error) {

	messageType := make([]byte, 1)
	if _, err := io.ReadFull(connection.GetTCPConnection(), messageType); err != nil {
		return 0, err
	}
	return messageType[0], nil
}

// GetDataLen 从连接中获取包头长度方法
func (dp *BaseDataPack) GetDataLen(connection iserver.IConnection) (uint32, error) {
	messageLen := make([]byte, 0)
	i := 0
	for {
		tempLen := make([]byte, 1)

		_, err := io.ReadFull(connection.GetTCPConnection(), tempLen)
		if err != nil {
			return 0, err
		}
		messageLen = append(messageLen, tempLen[0])
		if messageLen[i] < 128 {
			break
		}
		i++
	}
	var len uint32 = 0
	for index, element := range messageLen {
		if index == 0 {
			len += uint32(element) % (1 << 7)
		} else {
			len += uint32(element) % (1 << 7) * (1 << (index * 7))
		}
	}
	return len, nil
}

// GetWebSocketDataLen 从连接中获取包头长度方法
func (dp *BaseDataPack) GetWebSocketDataLen(data []byte) (uint32, error) {
	dataBuff := bytes.NewBuffer(data)
	messageLen := make([]byte, 0)
	i := 0
	for {
		tempLen := make([]byte, 1)
		err := binary.Read(dataBuff, binary.BigEndian, &tempLen)
		if err != nil {
			return 0, err
		}
		messageLen = append(messageLen, tempLen[0])
		if messageLen[i] < 128 {
			break
		}
		i++
	}
	var len uint32 = 0
	for index, element := range messageLen {
		if index == 0 {
			len += uint32(element) % (1 << 7)
		} else {
			len += uint32(element) % (1 << 7) * (1 << (index * 7))
		}
	}
	return len, nil
}


// GetDataLenList 从数据中获取包长度List
func (dp *BaseDataPack) GetDataLenList(dataLen int) []byte {
	lenList := make([]byte, 0)
	for {
		if dataLen <= 0 {
			break
		}
		temp := dataLen % (1 << 7)
		dataLen /= 1 << 7
		if dataLen > 0 {
			temp |= 0x80
		}
		lenList = append(lenList, byte(temp))
	}
	if len(lenList) == 0 {
		lenList = append(lenList, 0)
	}
	return lenList
}

// Pack 封包方法
func (dp *BaseDataPack) Pack(message imodel.IMessage) ([]byte, error) {
	//创建一个存放byte字节流的缓冲
	dataBuff := bytes.NewBuffer([]byte{})
	///写入header
	msgHeader := message.GetMsgId()<<4 | message.GetReserved()
	if err := binary.Write(dataBuff, binary.BigEndian, msgHeader); err != nil {
		return nil, err
	}

	//计算数据长度数组
	msgLenList := dp.GetDataLenList(len(message.GetData().([]byte)))
	//将dataLen写入dataBuff
	if err := binary.Write(dataBuff, binary.BigEndian, msgLenList); err != nil {
		return nil, err
	}

	//将data数据写入dataBuff
	if err := binary.Write(dataBuff, binary.BigEndian, message.GetData()); err != nil {
		return nil, err
	}
	return dataBuff.Bytes(), nil
}

// UnPack 拆包方法 (分两步 1.读取固定长度的head --> 消息内容的长度和消息的类型 2.根据消息内容的长度再次进行读写 --> 从conn中读取消息内容)
func (dp *BaseDataPack) UnPack(binaryData []byte) (imodel.IMessage, error) {
	////判断dataLen是否超出最大包长度
	//if utils.GetConfig().MaxPackageSize > 0 && msg.DataLen > utils.GetConfig().MaxPackageSize {
	//	return nil, errors.New("[UnPack] too Large msg data")
	//}
	return nil, nil
}

func NewBaseDataPack() *BaseDataPack {
	dp := &BaseDataPack{}
	return dp
}
